import base64
import json
import pickle

from django.shortcuts import render

# Create your views here.
from django import http
from django.views import View

# 购物车管理
from django_redis import get_redis_connection

from apps.goods.models import SKU
from utils.response_code import RETCODE


class CartsView(View):
    # 添加购物车逻辑
    '''
       0.接收数据,验证数据
       1.判断用户是否登陆
       2.登陆用户保存在redis中
           2.1 连接redis
           2.2 hash
               set
           2.3 返回相应
       3.未登录用户保存在cookie中

           3.1 组织字典数据
           3.2 对字典进行base64处理
           3.3 设置cookie
           3.4 返回相应
    '''

    # 添加购物车
    def post(self, request):
        # 接收数据
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected', True)
        # 校验数据
        if not all([sku_id, count]):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '缺少必传参数'})

        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '商品不存在'})

        try:
            count = int(count)
        except Exception as e:
            count = 1

        # 判断用户是否登陆
        user = request.user
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            '''
            redis_conn.hset('carts:%s' % user.id, sku_id, count)
            redis_conn.sadd('selected:%s' % user.id, sku_id)
            '''
            # 管道
            pipeline = redis_conn.pipeline()
            # hash
            pipeline.hincrby('carts:%s' % user.id, sku_id, count)
            # set
            pipeline.sadd('selected:%s' % user.id, sku_id)
            # 执行管道
            pipeline.execute()
            # 返回响应
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加购物车成功'})
        else:
            carts_cookie = request.COOKIES.get('carts')
            if carts_cookie is not None:
                # 解密
                carts = pickle.loads(base64.b64decode(carts_cookie))
            else:
                carts = {}
            if sku_id in carts:
                origin_count = carts[sku_id]['count']
                count += origin_count

            carts[sku_id] = {
                'count': count,
                'selected': selected
            }
            a = pickle.dumps(carts)
            b = base64.b64encode(a)
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '添加购物车成功'})
            response.set_cookie('carts', b, max_age=3600)
            return response

    # 展示购物车逻辑
    '''
    1.获取用户信息,根据用户信息进行判断
    2.登陆用户从redis中获取数据
        2.1 连接redis
        2.2 hash  {sku_id:count,sku_id:count...}
            set   {sku_id,sku_id}
        2.3 对商品id进行遍历
         2.4根据id获取商品的详细信息
         2.5将对象转换为字典
         2.6返回相应
    3.未登录用户从cookie中获取数据
        3.1 读取cookie中数据,并进行判断  {sku_id:{'count':xxx,'selected':True}}
        3.2 获取商品id
        3.3 对商品id进行遍历
        3.4 根据id获取商品的详细信息
        3.5将对象转换为字典
        3.6返回相应
    '''

    # 展示购物车
    def get(self, request):
        user = request.user
        # 用户登陆链接redis
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_cart = redis_conn.hgetall('carts:%s' % user.id)
            redis_selected = redis_conn.smembers('selected:%s' % user.id)

            carts = {}
            for sku_id, count in redis_cart.items():
                carts[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in redis_selected,
                }
        # 用户未登陆,链接cookie
        else:
            carts_cookie = request.COOKIES.get('carts')
            if carts_cookie is not None:
                carts = pickle.loads(base64.b64decode(carts_cookie))
            else:
                carts = {}

        ids = carts.keys()
        sku_list = []
        for id in ids:
            sku = SKU.objects.get(pk=id)
            sku_list.append({
                'id': sku.id,
                'name': sku.name,
                'count': carts.get(sku.id).get('count'),
                'selected': str(carts.get(sku.id).get('selected')),  # 将True，转'True'，方便json解析
                'default_image_url': sku.default_image.url,
                'price': str(sku.price),  # 从Decimal('10.2')中取出'10.2'，方便json解析
                'amount': str(sku.price * carts.get(sku.id).get('count')),
            })

        context = {
            'cart_skus': sku_list
        }
        return render(request, 'cart.html', context)

    # 修改购物车逻辑
    '''
    0.接收数据
    1.验证数据
    2.获取用户信息
    3.登陆用户更新redis
        3.1 连接redis
        3.2 hash
            set
        3.3 返回相应
    4.未登录用户更新cookie

        4.1 先获取cookie数据,判断cookie是否存在
        4.2 判断商品id是否在购物车中
        4.3 更新就可以
        4.4 把最新的数据进行加密处理
        4.5 更新cookie
        4.6 返回相应
    '''

    # 修改购物车
    def put(self, request):

        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')
        count = data.get('count')
        selected = data.get('selected')

        if not all([sku_id, count]):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数错误'})
        # 判断sku_id是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '没有此商品'})
        # 判断count是否为数字
        try:
            count = int(count)
        except Exception:
            count = 1

        user = request.user
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_conn.hset('carts:' % user.id, sku_id, count)
            if selected:
                redis_conn.sadd('selected:%s' % user.id, sku_id)
            else:
                redis_conn.sadd('selected:%s' % user.id, sku_id)

            # 返回响应
            new_sku = {
                'id': sku_id,
                'count': count,
                'selected': selected,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'amount': sku.price * count,
            }
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '修改购物车成功', 'cart_sku': new_sku})
        else:
            carts_cookie = request.COOKIES.get('carts')
            if carts_cookie is not None:
                carts = pickle.loads(base64.b64decode(carts_cookie))
            else:
                carts = {}
            if sku_id in carts:
                carts[sku_id] = {
                    'count': count,
                    'selected': selected
                }
            carts_coding = base64.b64encode(pickle.dumps(carts))

            new_sku = {
                'id': sku_id,
                'count': count,
                'selected': selected,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'amount': sku.price * count,
            }
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '修改购物车成功', 'cart_sku': new_sku})
            response.set_cookie('carts', carts_coding, max_age=3600)
            return response

    # 删除购物车逻辑
    '''
    1.接收数据
    2.验证数据
    3.获取用户
    4.登陆用户操作redis
        4.1 连接redis
        4.2 hash
            set
        4.3返回相应
    5.未登录用户操作cookie
        5.1 先读取cookie数据,判断数据是否存在
        5.2 判断sku_id 是否在数据中
        5.3 如果存在就删除
        5.4 对删除后的数据进行加密处理
        5.5 返回相应
    '''

    # 删除购物车
    def delete(self, request):

        # 获取数据
        data = json.loads(request.body.decode())
        sku_id = data.get('sku_id')

        # 判断sku_id是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '商品不存在'})
        # 获取用户
        user = request.user
        # 用户登陆
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            # hash
            redis_conn.hdel('carts:%s' % user.id, sku_id)
            # set
            redis_conn.srem('selected:%s' % user.id, sku_id)

            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除购物车成功'})
        # 用户未登录
        else:
            carts_cookie = request.COOKIES.get('carts')
            if carts_cookie is not None:
                carts = pickle.loads(base64.b64decode(carts_cookie))
            else:
                carts = {}
            if sku_id in carts:
                del carts[sku_id]

            carts_coding = base64.b64encode(pickle.dumps(carts))
            # 返回响应
            response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除购物车成功'})
            response.set_cookie('carts', carts_coding, max_age=3600)
            return response


# 全选购物车
class CartsSelectAllView(View):
    def put(self, request):
        # 接收数据
        data = json.loads(request.body.decode())
        selected = data.get('selected', True)
        # 校验参数
        if selected:
            if not isinstance(selected, bool):
                return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数错误'})
        # 判断用户是否登陆
        user = request.user
        # 登陆全选redis购物车
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            carts = redis_conn.hgetall('carts:%s' % user.id)
            ids = carts.keys()
            if selected:
                redis_conn.sadd('selected:%s' % user.id, ids)
            else:
                redis_conn.srem('selected:%s' % user.id, ids)
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '全选购物车成功'})
        # 未登录全选cookie购物车
        else:
            carts_cookie = request.COOKIES.get('carts')
            if carts_cookie is not None:
                carts = pickle.loads(base64.b64decode(carts_cookie))
                for sku_id in carts:
                    carts[sku_id]['selected'] = selected
                carts_coding = base64.b64encode(pickle.dumps(carts))
                response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '全选购物车成功'})
                response.set_cookie('carts', carts_coding, max_age=3600)
                return response

            else:
                return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '购物车为空'})


# 简单显示购物车数据展示
class CartsSimpleView(View):
    def get(self, request):
        user = request.user
        if user is not None and user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_cart = redis_conn.hgetall('carts:%s' % user.id)
            redis_selected = redis_conn.smembers('selected:%s' % user.id)
            carts = {}
            for sku_id, count in redis_cart.items():
                carts[int(sku_id)] = {
                    'count': count,
                    'selected': sku_id in redis_selected
                }
        else:
            carts_cookie = request.COOKIES.get('carts')
            if carts_cookie is not None:
                carts = pickle.loads(base64.b64decode(carts_cookie))
            else:
                carts = {}

            ids = carts.keys()
            sku_list = []
            for id in ids:
                sku = SKU.objects.get(id=id)
                sku_list.append({
                    'id': sku.id,
                    'name': sku.name,
                    'count': carts.get(sku.id).get('count'),
                    'default_image_url': sku.default_image.url
                })

            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok', 'sku_list': sku_list})
